/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ComNo;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author 6766371
 */
public class Cliente implements Runnable {

    private static int flag;
    private InputStream in;      //stream para envia dados
    private OutputStream out;    //stream para receber dados
    private Socket conMestre;    //socket de comunicacao com o Mestre
    private static String servidor;
    private static int servPorta;
    private List<String> files;                     //armazena a lista de arquivos que possui
    //Variáveis para tratar erros
    private final static int FALHA = 0;
    private final static int SUCESSO = 1;
    private final static int ARQEXISTENTE = 2;      //arquivo que está tentando ser criado já existe
    private final static int UKERRO = 3;            //erro desconhecido
    private final static int SERVERNOTFOUND = 4;

    public String getServidor() {
        return servidor;
    }

    public void setServidor(String servidor) {
        Cliente.servidor = servidor;
    }

    public int getServPorta() {
        return servPorta;
    }

    public void setServPorta(int servPorta) {
        Cliente.servPorta = servPorta;
        files = new ArrayList<String>();
    }

    public void Criar(BufferedReader br) throws IOException {
        String nArq;
        String entrada;                 //em caso de arquivo já existente a reopção é recebida por essa variável
        int statusCria = FALHA;


        System.out.println("Nome do arquivo: ");
        while (statusCria != SUCESSO) {
            nArq = br.readLine();
            NoComCliente cliente = new NoComCliente(getServidor(), getServPorta(), nArq);
            statusCria = cliente.CriaArquivo();

            switch (statusCria) {
                case SUCESSO:
                    files.add(nArq);
                    break;
                case FALHA:
                    System.out.println("Falha no sistema. Digite o nome do arquivo novamente: ");
                    break;
                case ARQEXISTENTE:
                    System.out.println("Arquivo existente:\n"
                            + "(1) Criar arquivo novamente com outro nome\n"
                            + "(2) Copiar o arquivo existente");          //verificar se cliente deseja ler o arquivo existente
                    entrada = br.readLine();
                    //implementar o q o cliente escolheu
                    if (entrada.equalsIgnoreCase("1")) {
                        statusCria = FALHA;
                        break;
                    } else if (entrada.equalsIgnoreCase("2")) {
                        Ler(br);
                        statusCria = SUCESSO;
                        break;
                    }
                case UKERRO:
                    System.out.println("Erro!\n Digite o nome do arquivo novamente: ");
                    break;
                case SERVERNOTFOUND:
                    System.out.println("Servidor nao encontrado. Redefina o servidor.");
                    break;
            }
        }
    }

    public void Excluir(BufferedReader br) throws IOException {
        String nArq;
        int index = -1;
        int statusExcluir = FALHA;


        System.out.println("Arquivo buscado: ");

        while (statusExcluir != SUCESSO) {
            nArq = br.readLine();

            NoComCliente clnt = new NoComCliente(getServidor(), getServPorta(), nArq);
            statusExcluir = clnt.ExcluirArquivo();

            switch (statusExcluir) {
                case SUCESSO:
                    files.remove(nArq);
                    break;
                case FALHA:
                    System.out.println("Arquivo inexistente. Digite o nome do arquivo novamente: ");
                    break;
                case ARQEXISTENTE:
                    statusExcluir = SUCESSO;
                    break;
                //implementar o q o cliente escolheu
                case UKERRO:
                    System.out.println("Erro!\n Digite o nome do arquivo novamente: ");
                    break;
                case SERVERNOTFOUND:
                    System.out.println("Servidor nao encontrado. Redefina o servidor.");
                    break;
            }
        }
    }

    public void Ler(BufferedReader br) throws IOException {
        String nArq;

        System.out.println("Arquivo buscado: ");
        nArq = br.readLine();

        NoComCliente clnt = new NoComCliente(getServidor(), getServPorta(), nArq);
        clnt.CopiarArquivo();                //realiza a operacao do cliente, requisicao de arquivo

    }

    public int InformaBD() throws IOException {
        try {
            conMestre = new Socket(servidor, servPorta);    //cria a socket para estabelecer conexão com o servidor

            System.out.println("Conectando ao mestre... enviando a mensagem");

            in = conMestre.getInputStream();          //stream para receber a resposta do servidor
            out = conMestre.getOutputStream();       //stream para enviar a mensagem ao servidor
        } catch (IOException | IllegalArgumentException | SecurityException ex) {
            System.out.println("    Falha: " + ex.getMessage());
            return FALHA;
        }
        PrintStream envio = new PrintStream(out);

        //envia opcao DE INFORMAR
        envio.println("5");
        envio.flush();

        //Lê os nomes dos arquivos na pasta /opt/grupo08/
        File arquivos[];
        File diretorio = new File("/opt/grupo08/");
        arquivos = diretorio.listFiles();
        //envia o numero de arquivos
        envio.println(arquivos.length);
        envio.flush();
        //Checa o tamanho dos arquivos    
        for (int i = 0; i < arquivos.length; i++) {
            Scanner scan = new Scanner(in);
            String respostaEnd = new String();     //auxiliar só para teste
            int respostaTam = 0;                   //auxiliar só para teste
            int respostaMestre = FALHA;

            //envia o nome do arquivo
            envio.println(arquivos[i].getName());
            envio.flush();
            //envia o tamanho do arquivo
            envio.println(arquivos[i].length());
            envio.flush();
            //envia o host
            envio.println(InetAddress.getLocalHost().getHostName());
            envio.flush();

            if (scan.hasNext()) {
                respostaMestre = Integer.parseInt(scan.nextLine());
            }
            if (respostaMestre == ARQEXISTENTE) {
                System.out.println("    Falha no envio das informacoes: Arquivo ja existe.");
            } else if (respostaMestre == UKERRO) {
                System.out.println("    Falha no envio das informacoes: Erro Desconhecido");
            }
        }
        in.close();
        out.close();
        conMestre.close();
        envio.close();
        //retorna sucesso
        return SUCESSO;

    }

    public void Atualizar(BufferedReader br) throws IOException {
        String nArq;

        System.out.println("    Arquivo buscado: ");
        nArq = br.readLine();

        NoComCliente clnt = new NoComCliente(getServidor(), getServPorta(), nArq);
        int statusAtualizar = clnt.AtualizarArquivo();

        switch (statusAtualizar) {
            case SUCESSO:
                //System.out.println("(Exclui)Lista de arquivos no nó "+InetAddress.getLocalHost().getHostName() + " "+files.toString());
                break;
            case FALHA:
                System.out.println("Arquivo inexistente!");
                break;
            case ARQEXISTENTE:
                break;
            //implementar o q o cliente escolheu
            case UKERRO:
                System.out.println("Erro!");
                break;
            case SERVERNOTFOUND:
                System.out.println("Servidor nao encontrado. Redefina o servidor.");
                break;
        }
    }

    @Override
    public void run() {
        try {
            System.out.println("Informando arquivos ao servidor.");
            int statusInformar = FALHA;
            statusInformar = InformaBD();
        } catch (IOException ex) {
            Logger.getLogger(Cliente.class.getName()).log(Level.SEVERE, null, ex);
        }
        while (true) {
            try {
                System.out.println("Digite a operacao desejada: \n"
                        + "(1) Ler\n"
                        + "(2) Excluir\n"
                        + "(3) Criar\n"
                        + "(4) Atualizar\n");

                //lê do teclado a operação desejada pelo usuário
                InputStreamReader in = new InputStreamReader(System.in);
                BufferedReader br = new BufferedReader(in);

                String entrada = new String();
                do {

                    entrada = br.readLine();

                } while (((entrada.compareTo("1")) != 0) && ((entrada.compareTo("2")) != 0) && ((entrada.compareTo("3")) != 0) && ((entrada.compareTo("4")) != 0));

                flag = Integer.parseInt(entrada);
                if (flag == 1) {                 //se o no quiser requisitar um arquivo
                    Ler(br);
                } else if (flag == 2) {                     // se o nó tiver que enviar um arquivo
                    Excluir(br);
                } else if (flag == 3) {                     // se o nó tiver que enviar um arquivo
                    Criar(br);
                } else if (flag == 4) {
                    Atualizar(br);
                }

            } catch (IOException ex) {
                Logger.getLogger(Cliente.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}
